#include "libutilsconfig.h"
#include "Mutex.h"

LIB_NS::Mutex::Mutex()
{
#ifdef _MSC_VER
	InitializeCriticalSection( &m_mutex );
#else
	m_count = 0;
	m_threadID = 0;
	//pthread_mutexattr_t attr;
	//pthread_mutexattr_init(&attr);
	//pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
	//pthread_mutex_init(&m_mutex, &attr);
	pthread_mutex_init( &m_mutex, 0 );
#endif
}

LIB_NS::Mutex::~Mutex()
{
#ifdef _MSC_VER
	DeleteCriticalSection( &m_mutex );
#else
	pthread_mutex_destroy( &m_mutex );
#endif
}

void LIB_NS::Mutex::lock()
{
#ifdef _MSC_VER
	EnterCriticalSection( &m_mutex );
#else
	if ( m_count && m_threadID == pthread_self() )
	{ ++m_count; return ; }
	pthread_mutex_lock( &m_mutex );
	++m_count;
	m_threadID = pthread_self();
#endif
}

void LIB_NS::Mutex::unlock()
{
#ifdef _MSC_VER
	LeaveCriticalSection( &m_mutex );
#else
	if ( m_count > 1 )
	{ m_count--; return ; }
	--m_count;
	m_threadID = 0;
	pthread_mutex_unlock( &m_mutex );
#endif
}

LIB_NS::Locker::Locker( Mutex& mutex ) : m_mutex( mutex )
{
	m_mutex.lock();
}

LIB_NS::Locker::~Locker()
{
	m_mutex.unlock();
}

LIB_NS::ReverseLocker::ReverseLocker( Mutex& mutex ) : m_mutex( mutex )
{
	m_mutex.unlock();
}

LIB_NS::ReverseLocker::~ReverseLocker()
{
	m_mutex.lock();
}